from fastapi import HTTPException

import service.auth_service
from cache import REDIS_LOCK
from schemas.auth import GetTokenResponse, GetTokenRequest, RefreshTokenRequest, RefreshTokenResponse, \
    RegisterAppResponse, RegisterAppRequest, LoginAppResponse, LoginAppRequest, LogoutAppRequest, LogoutAppResponse, \
    UnregisterAppRequest, UnregisterAppResponse, InvalidateTokenRequest, InvalidateTokenResponse
from service.auth_service import getUserToken, getAppAuthInfo, refreshAuth, invalidateTokens
from utils.auth_util import verify, is_valid_timestamp


def init_routes(app):
    @app.post("/scaffolding/api/auth/getToken", response_model=GetTokenResponse)
    def getToken(request: GetTokenRequest):
        if not is_valid_timestamp(request.timestamp):
            raise HTTPException(status_code=400, detail="Timestamp Not Valid")

        if REDIS_LOCK.acquire(appId=request.appId):
            try:
                authInfo = getAppAuthInfo(request.appId)
                if authInfo.appSecret == '':
                    raise HTTPException(status_code=404, detail="Failed,Auth Info Not Exsited")
                else:
                    if verify(request, authInfo):
                        return getUserToken(request.appId, authInfo.appName)
                    else:
                        raise HTTPException(status_code=401, detail="Failed, APP Sign Not Right")
            finally:
                REDIS_LOCK.release(appId=request.appId)
        else:
            raise HTTPException(status_code=504, detail="Timeout, please retry")

    @app.post("/scaffolding/api/auth/refreshToken", response_model=RefreshTokenResponse)
    def refreshToken(request: RefreshTokenRequest):
        if REDIS_LOCK.acquire(appId=request.appId):
            try:
                authInfo = getAppAuthInfo(request.appId)
                if not authInfo:
                    raise HTTPException(status_code=404, detail="Failed,Auth Info Not Exsited")
                else:
                    return refreshAuth(request)
            finally:
                REDIS_LOCK.release(appId=request.appId)
        else:
            raise HTTPException(status_code=504, detail="Timeout, please retry")

    @app.post("/scaffolding/api/auth/checkToken")
    def checkToken():
        return {
            "result": "Token Valid"
        }

    @app.post("/scaffolding/api/auth/invalidate")
    def invalidateToken(request: InvalidateTokenRequest):
        if not is_valid_timestamp(request.timestamp):
            raise HTTPException(status_code=400, detail="Timestamp Not Valid")

        if REDIS_LOCK.acquire(appId=request.appId):
            try:
                authInfo = getAppAuthInfo(request.appId)
                if authInfo.appSecret == '':
                    raise HTTPException(status_code=404, detail="Failed,Auth Info Not Exsited")
                else:
                    if verify(request, authInfo):
                        invalidateTokens(request.appId)

                        return InvalidateTokenResponse(result='Invalidate Completed')
                    else:
                        raise HTTPException(status_code=401, detail="Failed, APP Sign Not Right")
            finally:
                REDIS_LOCK.release(appId=request.appId)
        else:
            raise HTTPException(status_code=504, detail="Timeout, please retry")

    @app.post("/scaffolding/api/auth/registerApp", response_model=RegisterAppResponse)
    def registerApp(request: RegisterAppRequest):
        authInfo = getAppAuthInfo(request.appId)
        if authInfo.appSecret == '':
            raise HTTPException(status_code=404, detail="Failed,Auth Info Not Exsited")
        else:
            if verify(request, authInfo):
                if service.auth_service.registerApp(request.appId, request.userId, request.userPass):
                    return RegisterAppResponse(result='Registered Completed')
                else:
                    raise HTTPException(status_code=409, detail="FAILED, User Exsited")
            else:
                raise HTTPException(status_code=401, detail="Failed, APP Secret Not Right")

    @app.post("/scaffolding/api/auth/loginApp", response_model=LoginAppResponse)
    def loginApp(request: LoginAppRequest):
        return service.auth_service.loginApp(request.appId, request.userId, request.userPass)

    @app.post("/scaffolding/api/auth/logoutApp", response_model=LogoutAppResponse)
    def logoutApp(request: LogoutAppRequest):
        return service.auth_service.logoutApp(request.appId, request.userId,
                                              request.accessToken)

    @app.post("/scaffolding/api/auth/unregisterApp", response_model=UnregisterAppResponse)
    def unregisterApp(request: UnregisterAppRequest):
        return service.auth_service.unregisterApp(request.appId, request.userId, request.userPass)
